package com.zenithmind.exam.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zenithmind.common.annotation.DataCache;
import com.zenithmind.common.exception.BusinessException;
import com.zenithmind.exam.mapper.ExamCategoryMapper;
import com.zenithmind.exam.pojo.entity.ExamCategory;
import com.zenithmind.exam.service.ExamCategoryService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * 考试分类服务实现类
 * 
 * @author ZenithMind
 * @since 2024-07-01
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class ExamCategoryServiceImpl extends ServiceImpl<ExamCategoryMapper, ExamCategory> implements ExamCategoryService {

    private final ExamCategoryMapper examCategoryMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean createCategory(ExamCategory category) {
        try {
            // 验证分类名称是否重复
            if (isCategoryNameExists(category.getName(), category.getParentId(), null)) {
                throw new BusinessException("分类名称已存在");
            }

            // 设置层级
            if (StringUtils.hasText(category.getParentId())) {
                ExamCategory parentCategory = getById(category.getParentId());
                if (parentCategory == null) {
                    throw new BusinessException("父分类不存在");
                }
                category.setLevel(parentCategory.getLevel() + 1);
            } else {
                category.setLevel(1);
            }

            // 设置默认值
            if (category.getSortOrder() == null) {
                category.setSortOrder(0);
            }
            if (category.getStatus() == null) {
                category.setStatus(1);
            }

            boolean result = save(category);
            if (result) {
                log.info("创建考试分类成功，分类ID: {}, 分类名称: {}", category.getId(), category.getName());
            }
            return result;
        } catch (Exception e) {
            log.error("创建考试分类失败", e);
            throw new BusinessException("创建考试分类失败: " + e.getMessage());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateCategory(ExamCategory category) {
        try {
            ExamCategory existingCategory = getById(category.getId());
            if (existingCategory == null) {
                throw new BusinessException("分类不存在");
            }

            // 验证分类名称是否重复
            if (isCategoryNameExists(category.getName(), category.getParentId(), category.getId())) {
                throw new BusinessException("分类名称已存在");
            }

            // 不允许将分类设置为自己的子分类
            if (StringUtils.hasText(category.getParentId()) && 
                isDescendantCategory(category.getId(), category.getParentId())) {
                throw new BusinessException("不能将分类设置为自己的子分类");
            }

            boolean result = updateById(category);
            if (result) {
                log.info("更新考试分类成功，分类ID: {}, 分类名称: {}", category.getId(), category.getName());
            }
            return result;
        } catch (Exception e) {
            log.error("更新考试分类失败", e);
            throw new BusinessException("更新考试分类失败: " + e.getMessage());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteCategory(String categoryId) {
        try {
            if (!canDeleteCategory(categoryId)) {
                throw new BusinessException("该分类下存在子分类或考试，无法删除");
            }

            boolean result = removeById(categoryId);
            if (result) {
                log.info("删除考试分类成功，分类ID: {}", categoryId);
            }
            return result;
        } catch (Exception e) {
            log.error("删除考试分类失败", e);
            throw new BusinessException("删除考试分类失败: " + e.getMessage());
        }
    }

    @Override
    @DataCache(key = "'exam:category:' + #categoryId", expireTime = 30, timeUnit = TimeUnit.MINUTES)
    public ExamCategory getCategoryById(String categoryId) {
        return getById(categoryId);
    }

    @Override
    @DataCache(key = "'exam:category:children:' + #parentId", expireTime = 15, timeUnit = TimeUnit.MINUTES)
    public List<ExamCategory> getChildCategories(String parentId) {
        return examCategoryMapper.selectByParentId(parentId);
    }

    @Override
    @DataCache(key = "'exam:category:root'", expireTime = 30, timeUnit = TimeUnit.MINUTES)
    public List<ExamCategory> getRootCategories() {
        return examCategoryMapper.selectRootCategories();
    }

    @Override
    @DataCache(key = "'exam:category:tree'", expireTime = 30, timeUnit = TimeUnit.MINUTES)
    public List<ExamCategory> getCategoryTree() {
        return examCategoryMapper.selectCategoryTree();
    }

    @Override
    public IPage<ExamCategory> getCategoryPage(Page<ExamCategory> page, String name, Integer status, String parentId) {
        return examCategoryMapper.selectCategoryPage(page, name, status, parentId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateCategoryStatus(String categoryId, Integer status) {
        try {
            ExamCategory category = new ExamCategory();
            category.setId(categoryId);
            category.setStatus(status);
            
            boolean result = updateById(category);
            if (result) {
                log.info("更新考试分类状态成功，分类ID: {}, 状态: {}", categoryId, status);
            }
            return result;
        } catch (Exception e) {
            log.error("更新考试分类状态失败", e);
            throw new BusinessException("更新考试分类状态失败: " + e.getMessage());
        }
    }

    @Override
    public boolean canDeleteCategory(String categoryId) {
        // 检查是否有子分类
        Integer childCount = examCategoryMapper.countByParentId(categoryId);
        if (childCount > 0) {
            return false;
        }

        // 检查是否有关联的考试或题库
        try {
            // 检查是否有关联的考试
            // 注意：这里需要根据实际的Exam实体和Mapper来实现
            // LambdaQueryWrapper<Exam> examQuery = new LambdaQueryWrapper<>();
            // examQuery.eq(Exam::getCategoryId, categoryId);
            // long examCount = examMapper.selectCount(examQuery);
            // if (examCount > 0) {
            //     log.warn("分类下存在考试，无法删除，分类ID: {}, 考试数量: {}", categoryId, examCount);
            //     return false;
            // }

            // 检查是否有关联的题库
            // LambdaQueryWrapper<QuestionBank> bankQuery = new LambdaQueryWrapper<>();
            // bankQuery.eq(QuestionBank::getCategoryId, categoryId);
            // long bankCount = questionBankMapper.selectCount(bankQuery);
            // if (bankCount > 0) {
            //     log.warn("分类下存在题库，无法删除，分类ID: {}, 题库数量: {}", categoryId, bankCount);
            //     return false;
            // }

            log.info("检查分类关联数据，分类ID: {}", categoryId);
            // 暂时返回true，等相关功能实现后再完善
        } catch (Exception e) {
            log.error("检查分类关联数据失败，分类ID: {}", categoryId, e);
            return false; // 出错时不允许删除
        }
        
        return true;
    }

    @Override
    @DataCache(key = "'exam:category:enabled'", expireTime = 30, timeUnit = TimeUnit.MINUTES)
    public List<ExamCategory> getEnabledCategories() {
        return examCategoryMapper.selectEnabledCategories();
    }

    /**
     * 检查分类名称是否存在
     */
    private boolean isCategoryNameExists(String name, String parentId, String excludeId) {
        LambdaQueryWrapper<ExamCategory> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ExamCategory::getName, name);
        
        if (StringUtils.hasText(parentId)) {
            queryWrapper.eq(ExamCategory::getParentId, parentId);
        } else {
            queryWrapper.isNull(ExamCategory::getParentId);
        }
        
        if (StringUtils.hasText(excludeId)) {
            queryWrapper.ne(ExamCategory::getId, excludeId);
        }
        
        return count(queryWrapper) > 0;
    }

    /**
     * 检查是否为后代分类
     */
    private boolean isDescendantCategory(String ancestorId, String descendantId) {
        if (!StringUtils.hasText(descendantId)) {
            return false;
        }
        
        ExamCategory category = getById(descendantId);
        while (category != null && StringUtils.hasText(category.getParentId())) {
            if (ancestorId.equals(category.getParentId())) {
                return true;
            }
            category = getById(category.getParentId());
        }
        
        return false;
    }
}
